﻿using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Magnum.Reflection;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Collections.Concurrent;

namespace CobaCoba
{
    [Serializable, ProtoBuf.ProtoContract, DataContract]
    public class InstructionData : ImessageContent
    {
        public override object Clone()
        {
            return this.MemberwiseClone();
        }

        private DateTime? _inReinbursementDate;
        private DateTime _inSettlementDate;
        private DateTime? _inLastUpdateTimeStamp;
        private DateTime _inTradeDate;

        private decimal _inSecuritiesQuantity;
        private decimal _inSettlementAmount;

        public override Type GetClassType()
        {
            return this.GetType();
        }


        [ProtoBuf.ProtoMember(1)]
        [ElementIn(1, "accountParticipantCash")]
        [DataMember]
        public virtual string AccountParticipantCash { get; set; }

        [ProtoBuf.ProtoMember(2)]
        [DataMember]
        public virtual DateTime? InReimbursementDate
        {
            get { return _inReinbursementDate; }
            set { _inReinbursementDate = value; }
        }

        [ProtoBuf.ProtoIgnore]
        [ElementIn(2, "reimbursementDate")]
        public virtual string ReimbursementDate
        {
            get
            {
                return _inReinbursementDate == null ? string.Empty :
                    ((DateTime)_inReinbursementDate).ToString("yyyyMMdd");
            }
            set
            {
                _inReinbursementDate = CommonUtil.ConvertStringToDateTimeNull(value);
            }
        }

        [ProtoBuf.ProtoMember(3)]
        [ElementIn(3, "instructionType")]
        [DataMember]
        public override string InstructionType
        {
            get { return base.InstructionType; }
            set { base.InstructionType = value; }
        }

        [ProtoBuf.ProtoMember(4)]
        [ElementIn(4, "relatedInstruction")]
        [DataMember]
        public virtual string RelatedInstruction { get; set; }

        [ProtoBuf.ProtoMember(5)]
        [ElementIn(5, "counterParty")]
        [DataMember]
        public virtual string CounterParty { get; set; }

        [ProtoBuf.ProtoMember(6)]
        [ElementIn(6, "canceling")]
        [DataMember]
        public virtual string Canceling { get; set; }

        [ProtoBuf.ProtoMember(7)]
        [ElementIn(7, "currency")]
        [DataMember]
        public virtual string Currency { get; set; }

        [ProtoBuf.ProtoMember(8)]
        [ElementIn(8, "accountParticipant")]
        [DataMember]
        public virtual string AccountParticipant { get; set; }

        [ProtoBuf.ProtoMember(9)]
        [ElementIn(9, "blockingReason")]
        [DataMember]
        public virtual string BlockingReason { get; set; }

        [ProtoBuf.ProtoMember(10)]
        [ElementIn(10, "status")]
        [DataMember]
        public override string Status
        {
            get { return base.Status; }
            set { base.Status = value; }
        }

        [ProtoBuf.ProtoMember(11)]
        [DataMember]
        public override DateTime InSettlementDate
        {
            get { return _inSettlementDate; }
            set { base.InSettlementDate = _inSettlementDate = value; }
        }

        [ProtoBuf.ProtoIgnore]
        [ElementIn(11, "settlementDate")]
        public virtual string SettlementDate
        {
            get
            {
                return ((DateTime)_inSettlementDate).ToString("yyyyMMdd");
            }
            set
            {
                _inSettlementDate = CommonUtil.ConvertStringToDateTime(value);
            }
        }

        [ProtoBuf.ProtoMember(12)]
        [DataMember]
        public virtual decimal InSecurityQuantity
        {
            get { return _inSecuritiesQuantity; }
            set { _inSecuritiesQuantity = value; }
        }

        [ProtoBuf.ProtoIgnore]
        [ElementIn(12, "securityQuantity")]
        public virtual string SecurityQuantity
        {
            get
            {
                return string.Format("{0:0.####}", _inSecuritiesQuantity);
            }
            set
            {
                _inSecuritiesQuantity = string.IsNullOrEmpty(value) ? 0 :
                    decimal.Parse(value, System.Globalization.NumberStyles.AllowDecimalPoint,
                    System.Globalization.CultureInfo.CreateSpecificCulture("en-EN"));
            }
        }

        [ProtoBuf.ProtoMember(13)]
        [ElementIn(13, "matchable")]
        [DataMember]
        public virtual string Matchable { get; set; }

        [ProtoBuf.ProtoMember(14)]
        [ElementIn(14, "accountCounterParty")]
        [DataMember]
        public virtual string AccountCounterParty { get; set; }

        [ProtoBuf.ProtoMember(15)]
        [ElementIn(15, "externalReference")]
        [DataMember]
        public override string ExternalReference
        {
            get { return base.ExternalReference; }
            set { base.ExternalReference = value; }
        }

        [ProtoBuf.ProtoMember(16)]
        [DataMember]
        public virtual decimal InSettlementAmount
        {
            get { return _inSettlementAmount; }
            set { _inSettlementAmount = value; }
        }

        [ProtoBuf.ProtoIgnore]
        [ElementIn(16, "settlementAmount")]
        public virtual string SettlementAmount
        {
            get
            {
                return string.Format("{0:0.####}", _inSettlementAmount);
            }
            set
            {
                _inSettlementAmount = string.IsNullOrEmpty(value) ? 0 :
                    decimal.Parse(value, System.Globalization.NumberStyles.AllowDecimalPoint,
                    System.Globalization.CultureInfo.CreateSpecificCulture("en-EN"));
            }
        }

        [ProtoBuf.ProtoMember(17)]
        [ElementIn(17, "externalBankAccount")]
        [DataMember]
        public virtual string ExternalBankAccount { get; set; }

        [ProtoBuf.ProtoMember(18)]
        [ElementIn(18, "description")]
        [DataMember]
        public virtual string Description { get; set; }

        [ProtoBuf.ProtoMember(19)]
        [DataMember]
        public virtual DateTime? InLastUpdateTimestamp
        {
            get { return _inLastUpdateTimeStamp; }
            set { _inLastUpdateTimeStamp = value; }
        }

        [ProtoBuf.ProtoIgnore]
        [ElementIn(19, "lastUpdateTimestamp")]
        public virtual string LastUpdateTimestamp
        {
            get
            {
                return _inLastUpdateTimeStamp == null ? string.Empty :
                    ((DateTime)_inLastUpdateTimeStamp).ToString("yyyyMMddHHmmssfff");
            }
            set
            {
                _inLastUpdateTimeStamp = CommonUtil.ConvertStringToDateTimeNull(value);
            }
        }

        [ProtoBuf.ProtoMember(20)]
        [ElementIn(20, "security")]
        [DataMember]
        public override string SecurityCode
        {
            get
            {
                return base.SecurityCode;
            }
            set
            {
                base.SecurityCode = value;
            }
        }

        [ProtoBuf.ProtoMember(21)]
        [DataMember]
        public override DateTime InTradeDate
        {
            get { return _inTradeDate; }
            set { base.InTradeDate = _inTradeDate = value; }
        }

        [ProtoBuf.ProtoIgnore]
        [ElementIn(21, "tradeDate")]
        public virtual string TradeDate
        {
            get
            {
                return ((DateTime)_inTradeDate).ToString("yyyyMMdd");
            }
            set
            {
                _inTradeDate = CommonUtil.ConvertStringToDateTime(value);
            }
        }

        [ProtoBuf.ProtoMember(22)]
        [ElementIn(22, "uniqueIdentifier")]
        [DataMember]
        public override string UniqueIdentifier
        {
            get
            {
                return base.UniqueIdentifier;
            }
            set
            {
                base.UniqueIdentifier = value;
            }
        }

        [ProtoBuf.ProtoMember(23)]
        [ElementIn(23, "priority")]
        [DataMember]
        public virtual string Priority { get; set; }

        [ProtoBuf.ProtoMember(24)]
        [ElementIn(24, "participant")]
        [DataMember]
        public virtual string Participant { get; set; }

        [ProtoBuf.ProtoMember(25)]
        [DataMember]
        public virtual string SecurityCodeType { get; set; }

        [ProtoBuf.ProtoIgnore]
        public override string TypeIncomingClassName
        {
            get { return "InstructionData"; }
        }

        [ProtoBuf.ProtoIgnore]
        public override string TypeOutgoingClassName
        {
            get { return base.TypeOutgoingClassName; }
        }


        [ProtoBuf.ProtoIgnore]
        public override string Extension
        {
            get { return base.Extension; }
        }

        [ProtoBuf.ProtoMember(26)]
        [DataMember]
        public override string CoreId { get; set; }
    }

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
    public class ElementInAttribute : Attribute
    {
        public ElementInAttribute(int sequence, string parameter)
        {
            this.Sequence = sequence;
            this.Element = parameter;
        }

        public string Element { get; set; }
        public int Sequence { get; set; }
    }

    [Serializable, ProtoBuf.ProtoContract]
    public class    ImessageContent : ICloneable
    {

        public virtual Type GetClassType()
        {
            return this.GetType();
        }

        [ProtoBuf.ProtoMember(1)]
        public virtual string ExternalReference { get; set; }

        [ProtoBuf.ProtoMember(2)]
        public virtual DateTime InTradeDate { get; set; }

        [ProtoBuf.ProtoMember(3)]
        public virtual DateTime InSettlementDate { get; set; }

        [ProtoBuf.ProtoMember(4)]
        public virtual string Status { get; set; }

        [ProtoBuf.ProtoMember(5)]
        public virtual string TypeIncomingClassName { get; set; }

        [ProtoBuf.ProtoMember(6)]
        public virtual string TypeOutgoingClassName { get; set; }

        [ProtoBuf.ProtoMember(7)]
        public virtual string InstructionType { get; set; }

        [ProtoBuf.ProtoMember(8)]
        public virtual string Extension { get; set; }

        [ProtoBuf.ProtoMember(9)]
        public virtual string CoreId { get; set; }

        [ProtoBuf.ProtoMember(10)]
        public virtual string SecurityCode { get; set; }

        [ProtoBuf.ProtoMember(11)]
        public virtual Guid IncomingId { get; set; }

        [ProtoBuf.ProtoMember(12)]
        public virtual string UniqueIdentifier { get; set; }

        public virtual object Clone()
        {
            return this.MemberwiseClone();
        }
    }

    public class CommonUtil
    {
        public static DateTime ConvertStringToDateTime(string strDate)
        {
            string[] fmtDate = new string[] { "yyyy", "yyyyMM", "yyyyMMdd", "yyyyMMddHH", "yyyyMMddHHmm",
                "yyyyMMddHHmm","yyyyMMddHHmmss","yyyyMMddHHmmssfff"};

            return DateTime.ParseExact(strDate, fmtDate, System.Globalization.CultureInfo.InvariantCulture,
                System.Globalization.DateTimeStyles.None);
        }

        public static DateTime? ConvertStringToDateTimeNull(string strDate)
        {
            if (string.IsNullOrEmpty(strDate) || string.IsNullOrWhiteSpace(strDate))
            {
                return null;
            }
            else
            {
                string[] fmtDate = new string[] { "yyyy", "yyyyMM", "yyyyMMdd", "yyyyMMddHH", "yyyyMMddHHmm",
                "yyyyMMddHHmm","yyyyMMddHHmmss","yyyyMMddHHmmssfff"};

                return DateTime.ParseExact(strDate, fmtDate, System.Globalization.CultureInfo.InvariantCulture,
                    System.Globalization.DateTimeStyles.None);
            }
        }

        private static string[] BlackListGroup()
        {
            return new string[] {"--", ";--", "/*", "*/", "@@", 
                                " @", "char(", "char (", "nchar", "varchar", "nvarchar", "alter", 
                                "begin", "cast ", "cast(", "create", "cursor", "declare", "delete ", 
                                "drop ", " end ", "exec ", "execute", "fetch ", "insert", 
                                "kill ", "open ", "sys ", "sysobjects", "syscolumns", "select",
                                "table", "update ", "<Script", "<asp", "<html"};
        }

        public static bool ScreeningInputInjection(string input)
        {
            bool retVal = true;
            for (int i = 0; i <= BlackListGroup().Length - 1; i++)
            {
                if (input.IndexOf(BlackListGroup()[i], StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    retVal = false;
                }
            }
            return retVal;
        }

    }
    [Serializable, ProtoBuf.ProtoContract]
    public abstract class BaseMessage
    {
    }

    [Serializable, ProtoBuf.ProtoContract]
    public class CBestIncomingMessage : BaseMessage
    {

        [ProtoBuf.ProtoMember(1)]
        public string Type { get; private set; }
        [ProtoBuf.ProtoMember(2)]
        public string ClassName { get; private set; }
        [ProtoBuf.ProtoMember(3)]
        public string ExtRef { get; private set; }
        [ProtoBuf.ProtoMember(4)]
        public int Status { get; set; }
        [ProtoBuf.ProtoMember(5)]
        public DateTime? TradeDate { get; private set; }
        [ProtoBuf.ProtoMember(6)]
        public DateTime? SettleDate { get; private set; }
        [ProtoBuf.ProtoMember(7)]
        public ImessageContent MsgContent { get; private set; }
        [ProtoBuf.ProtoMember(8)]
        public string ErrMsg { get; set; }
        [ProtoBuf.ProtoMember(9)]
        public string CTAgentMessageId { get; set; }
        [ProtoBuf.ProtoMember(10)]
        public string InstructionType { get; set; }
        [ProtoBuf.ProtoMember(11)]
        public Guid IncomingId { get; set; }
        [ProtoBuf.ProtoMember(12)]
        public string SecurityCode { get; set; }
        [ProtoBuf.ProtoMember(13)]
        public string UniqueIdentifier { get; set; }


        public void Fill<T>(T mc) where T : ImessageContent
        {
            this.Type = "IncomingMessage";
            this.ExtRef = mc.ExternalReference;
            this.TradeDate = mc.InTradeDate;
            this.SettleDate = mc.InSettlementDate;
            this.MsgContent = mc;
            this.ClassName = mc.TypeIncomingClassName;
            this.InstructionType = mc.InstructionType;
            this.SecurityCode = mc.SecurityCode;
            this.IncomingId = mc.IncomingId;
            this.UniqueIdentifier = mc.UniqueIdentifier;
        }

    }

    public class CastDerivedToBase
    {

        public ImessageContent CastingContent(ImessageContent msgContent)
        {
            Type derivedType = msgContent.GetType();
            Type baseType = derivedType.BaseType;

            return (ImessageContent)this.FastInvoke<CastDerivedToBase, object>(new Type[] { derivedType, baseType },
                                     "Casting", msgContent);
        }

        public object Casting<DERIVED, BASE>(DERIVED objDerived) where BASE : new()
        {
            BASE objBase = new BASE();
            string msgContent = JsonConvert.SerializeObject(objDerived);
            objBase = JsonConvert.DeserializeObject<BASE>(msgContent);
            return objBase;
        }
    }

    public interface IRecordSerializer
    {
        object[] args { get; set; }

        void Serialize(Stream stream, string fileName, params object[] instances);
        IEnumerable Deserialize(Stream stream, Type outType, string fileName);
        IEnumerable Deserialize(IList records, Type outType);
    }
    public interface IEntry
    {
        //IEnumerable<T> GetRecords<T>();
        //IEnumerable GetRecords(Type outType);
        IEnumerable GetRecords();
        Type SourceType { get; set; }
        Type TargetType { get; set; }
        IRecordSerializer Serializer { get; set; }
        object MapperEngine { get; set; }
        string Name { get; }
        void WriteRecords(object records);
    }

    public class IncomingCTAgent //: Praweda.Core.DomainModel.EntityWithTypedId<long>
    {
        public IncomingCTAgent()
        {
        }
        public virtual string MessageId { get; set; }
        public virtual string DataContent { get; set; }
        public virtual int Status { get; set; }
        public virtual DateTime IncomingDate { get; set; }
    }
   
    
}
